﻿/*
 * Copyright (c) .NET Foundation and Contributors
 *
 * This software may be modified and distributed under the terms
 * of the MIT license. See the LICENSE file for details.
 *
 * https://github.com/piranhacms/piranha.core
 *
 */

using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Piranha.Models;

namespace Piranha.Repositories;

internal class PageTypeRepository : IPageTypeRepository
{
    private readonly IDb _db;

    /// <summary>
    /// Default constructor.
    /// </summary>
    /// <param name="db">The current db connection</param>
    public PageTypeRepository(IDb db)
    {
        _db = db;
    }

    /// <summary>
    /// Gets all available models.
    /// </summary>
    /// <returns>The available models</returns>
    public async Task<IEnumerable<PageType>> GetAll()
    {
        var models = new List<PageType>();
        var types = await _db.PageTypes
            .AsNoTracking()
            .OrderBy(t => t.Id)
            .ToListAsync()
            .ConfigureAwait(false);

        foreach (var type in types)
        {
            models.Add(JsonConvert.DeserializeObject<PageType>(type.Body));
        }
        return models;
    }

    /// <summary>
    /// Gets the model with the specified id.
    /// </summary>
    /// <param name="id">The unique i</param>
    /// <returns></returns>
    public async Task<PageType> GetById(string id)
    {
        var type = await _db.PageTypes
            .AsNoTracking()
            .FirstOrDefaultAsync(t => t.Id == id)
            .ConfigureAwait(false);

        if (type != null)
        {
            return JsonConvert.DeserializeObject<PageType>(type.Body);
        }
        return null;
    }

    /// <summary>
    /// Adds or updates the given model in the database
    /// depending on its state.
    /// </summary>
    /// <param name="model">The model</param>
    public async Task Save(PageType model)
    {
        var type = await _db.PageTypes
            .FirstOrDefaultAsync(t => t.Id == model.Id)
            .ConfigureAwait(false);

        if (type == null) {
            type = new Data.PageType
            {
                Id = model.Id,
                Created = DateTime.Now
            };
            await _db.PageTypes.AddAsync(type).ConfigureAwait(false);
        }
        type.CLRType = model.CLRType;
        type.Body = JsonConvert.SerializeObject(model);
        type.LastModified = DateTime.Now;

        await _db.SaveChangesAsync().ConfigureAwait(false);
    }

    /// <summary>
    /// Deletes the model with the specified id.
    /// </summary>
    /// <param name="id">The unique id</param>
    public async Task Delete(string id)
    {
        var type = await _db.PageTypes
            .FirstOrDefaultAsync(t => t.Id == id)
            .ConfigureAwait(false);

        if (type != null)
        {
            _db.PageTypes.Remove(type);
            await _db.SaveChangesAsync().ConfigureAwait(false);
        }
    }
}
